﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using Microsoft.TeamFoundation.WebAccess.WorkItemTracking.Controls;
using Microsoft.TeamFoundation.WorkItemTracking.Controls;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using TFSWorkflowControl.Common;



[assembly: WebResource(TFSWorkflowControl.TSWA.Consts.XAPResourceName, "application/x-silverlight-app")]
[assembly: WebResource(TFSWorkflowControl.TSWA.Consts.SLJSResourceName, "text/javascript")]
[assembly: WebResource(TFSWorkflowControl.TSWA.Consts.WorkflowJSResourceName, "text/javascript")]


namespace TFSWorkflowControl.TSWA
{

    [ToolboxData("<{0}:Workflow runat=server></{0}:Workflow>")]
    public class Workflow : BaseWorkItemWebControl
    {
        private const string IterationPathReferenceDate = "System.IterationPath";
        private const string StateReferenceName = "System.State";
        private const string ReasonReferenceName = "System.Reason";
        private const string ChangedDateReferenceName = "System.ChangedDate";
        private const string ChangedByReferenceName = "System.ChangedBy";
     
        const string slscript = @"
 <div id=""workflowcontrolHost"">
        <object data=""data:application/x-silverlight-2,"" type=""application/x-silverlight-2"" width=""100%"" height=""150"">
		  <param name=""source"" value=""{0}""/>		  
		  <param name=""background"" value=""white"" />
		  <param name=""minRuntimeVersion"" value=""3.0.40624.0"" />
		  <param name=""autoUpgrade"" value=""true"" />
		  <a href=""http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0"" style=""text-decoration:none"">
 			  <img src=""http://go.microsoft.com/fwlink/?LinkId=108181"" alt=""Get Microsoft Silverlight"" style=""border-style:none""/>
		  </a>
	    </object><iframe id=""_sl_historyFrame"" style=""visibility:hidden;height:0px;width:0px;border:0px""></iframe>
";

        public Workflow()
            : this(HtmlTextWriterTag.Div)
        {

        }

        internal Workflow(HtmlTextWriterTag tag)
            : base(tag)
        {

        }

        protected Workflow(string tag)
            : base(tag)
        {

        }

        private void CreateParam(HtmlGenericControl objectControl, string name, string value)
        {
            HtmlGenericControl param;
            param = new HtmlGenericControl("param");
            param.Attributes.Add("name", name);
            param.Attributes.Add("value", value);
            objectControl.Controls.Add(param);
        }

        protected override void CreateChildControls()
        {
            base.CreateChildControls();
            base.Page.ClientScript.RegisterClientScriptResource(this.GetType(), Consts.SLJSResourceName);
            //base.Page.ClientScript.RegisterClientScriptResource(this.GetType(), Consts.WorkflowJSResourceName);

            var objectControl = new HtmlGenericControl("object");
            objectControl.Attributes.Add("data", "data:application/x-silverlight-2,");
            objectControl.Attributes.Add("type", "application/x-silverlight-2");
            objectControl.Attributes.Add("width", "100%");
            objectControl.Attributes.Add("height", "150");
            
            
            CreateParam(objectControl, "source", this.Page.ClientScript.GetWebResourceUrl(this.GetType(), Consts.XAPResourceName));
            //  CreateParam(objectControl, "source", "/ClientBin/TFSWorkflowControl.TSWA.SL.xap");

            CreateParam(objectControl, "background", "white");
            CreateParam(objectControl, "minRuntimeVersion", "3.0.40624.0");
            CreateParam(objectControl, "autoUpgrade", "true");
            CreateParam(objectControl, "onLoad", String.Format("onWorkflowSLLoad_{0}", ClientID));
            Controls.Add(objectControl);


            
            var startupScript=String.Format(@"
WorkflowControl_{0} = undefined;

function loadWorkflow_{0}() {{
    {1}

}}

function onWorkflowSLLoad_{0}(sender, args) {{
            var control = sender.GetHost();
            WorkflowControl_{0} = control;            
            loadWorkflow_{0}()
}}
", ClientID, CreateScriptFromWorkItem());
            


            this.Page.ClientScript.RegisterStartupScript(this.GetType(), ClientID, startupScript, true);
        }

        private IList<GroupNameAndReference> GetAvailableGroupsFromWorkItem(WorkItem wi, Option option)
        {
            if (wi == null)
            {
                throw new ArgumentNullException("wi");
            }

            List<GroupNameAndReference> result = new List<GroupNameAndReference>();


            var iterationField = wi.GetField(IterationPathReferenceDate);


            result.Add(new GroupNameAndReference() { Name = iterationField.Name, Reference = iterationField.ReferenceName });

            var q = (from field in wi.Fields.Cast<Field>()
                     where
                        !option.FieldToIgnoreList.Contains(field.ReferenceName) &&
                        field.HasAllowedValuesList &&
                        String.Compare(field.ReferenceName, IterationPathReferenceDate, false) != 0 &&
                        field.IsEditable &&
                        String.Compare(field.ReferenceName, StateReferenceName, false) != 0 &&
                        String.Compare(field.ReferenceName, ReasonReferenceName, false) != 0 &&
                        !field.IsComputed
                     orderby field.Name
                     select new GroupNameAndReference() { Name = field.Name, Reference = field.ReferenceName });

            result.AddRange(q);
            return result;
        }

        

        public string CreateScriptFromWorkItem()
        {
            StringBuilder sb = new StringBuilder();

            sb.AppendFormat(@"
            var control = WorkflowControl_{0}
            var workflow = control.Content.Workflow;
            var revisions = control.Content.RevisionCollection;           
", ClientID);

            sb.Append(@"workflow.StartEditCollection();");

            WorkItem workItem = ((WorkItem)this.WorkItemDatasource);
            Option option = Option.ComputeOption(Properties);
            if (workItem != null)
            {
                var groups = GetAvailableGroupsFromWorkItem(workItem, option);
                sb.AppendLine();
                sb.AppendFormat(@"workflow.SetDefaultField(""{0}"");",option.DefaultField);
                foreach (Revision revision in workItem.Revisions.OfType<Revision>())
                {
                    var date = (DateTime)revision.Fields[ChangedDateReferenceName].Value;
                    var state =  revision.Fields[StateReferenceName].Value.ToString();
                    var who =  revision.Fields[ChangedByReferenceName].Value.ToString();
                    var reason =  revision.Fields[ReasonReferenceName].Value.ToString();

                    sb.AppendFormat(String.Format(@"revisions.AppendRev(""{0}"",""{1}"",""{2}"",{3},{4},{5});", 
                                        state, 
                                        who, 
                                        reason, 
                                        date.Year, 
                                        date.Month, 
                                        date.Day));
                    sb.AppendLine();
                    foreach (var group in groups)
                    {
                        string value = revision.GetFieldValue(group.Reference);

                        sb.AppendFormat(@"revisions.Set(""{0}"", ""{1}"");", group.Name, value);
                        sb.AppendLine();
                    }
                }

            }

     sb.Append("workflow.EndEditCollection();");
            var result = sb.ToString();
            return result;
        }

        public override string GetClientUpdateScript()
        {
            return CreateScriptFromWorkItem();
        }

    }
}